home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / perlman / man / perldsc.txt < prev    next >
Encoding:
Text File  |  1999-09-09  |  29.0 KB  |  817 lines

  1. NAME
  2.        perldsc - Perl Data Structures Cookbook
  3.  
  4. DESCRIPTION
  5.        The single feature most sorely lacking in the Perl
  6.        programming language prior to its 5.0 release was complex
  7.        data structures.  Even without direct language support,
  8.        some valiant programmers did manage to emulate them, but
  9.        it was hard work and not for the faint of heart.  You
  10.        could occasionally get away with the $m{$LoL,$b} notation
  11.        borrowed from awk in which the keys are actually more like
  12.        a single concatenated string "$LoL$b", but traversal and
  13.        sorting were difficult.  More desperate programmers even
  14.        hacked Perl's internal symbol table directly, a strategy
  15.        that proved hard to develop and maintain--to put it
  16.        mildly.
  17.  
  18.        The 5.0 release of Perl let us have complex data
  19.        structures.  You may now write something like this and all
  20.        of a sudden, you'd have a array with three dimensions!
  21.  
  22.            for $x (1 .. 10) {
  23.                for $y (1 .. 10) {
  24.                    for $z (1 .. 10) {
  25.                        $LoL[$x][$y][$z] =
  26.                            $x ** $y + $z;
  27.                    }
  28.                }
  29.            }
  30.  
  31.        Alas, however simple this may appear, underneath it's a
  32.        much more elaborate construct than meets the eye!
  33.  
  34.        How do you print it out?  Why can't you just say print
  35.        @LoL?  How do you sort it?  How can you pass it to a
  36.        function or get one of these back from a function?  Is is
  37.        an object?  Can you save it to disk to read back later?
  38.        How do you access whole rows or columns of that matrix?
  39.        Do all the values have to be numeric?
  40.  
  41.        As you see, it's quite easy to become confused.  While
  42.        some small portion of the blame for this can be attributed
  43.        to the reference-based implementation, it's really more
  44.        due to a lack of existing documentation with examples
  45.        designed for the beginner.
  46.  
  47.        This document is meant to be a detailed but understandable
  48.        treatment of the many different sorts of data structures
  49.        you might want to develop.  It should also serve as a
  50.        cookbook of examples.  That way, when you need to create
  51.        one of these complex data structures, you can just pinch,
  52.        pilfer, or purloin a drop-in example from here.
  53.  
  54.        Let's look at each of these possible constructs in detail.
  55.        There are separate documents on each of the following:
  56.  
  57.        o arrays of arrays
  58.  
  59.        o hashes of arrays
  60.  
  61.        o arrays of hashes
  62.  
  63.        o hashes of hashes
  64.  
  65.        o more elaborate constructs
  66.  
  67.        o recursive and self-referential data structures
  68.  
  69.        o objects
  70.  
  71.        But for now, let's look at some of the general issues
  72.        common to all of these types of data structures.
  73.  
  74. REFERENCES
  75.        The most important thing to understand about all data
  76.        structures in Perl -- including multidimensional
  77.        arrays--is that even though they might appear otherwise,
  78.        Perl @ARRAYs and %HASHes are all internally one-
  79.        dimensional.  They can only hold scalar values (meaning a
  80.        string, number, or a reference).  They cannot directly
  81.        contain other arrays or hashes, but instead contain
  82.        references to other arrays or hashes.
  83.  
  84.        You can't use a reference to a array or hash in quite the
  85.        same way that you would a real array or hash.  For C or
  86.        C++ programmers unused to distinguishing between arrays
  87.        and pointers to the same, this can be confusing.  If so,
  88.        just think of it as the difference between a structure and
  89.        a pointer to a structure.
  90.  
  91.        You can (and should) read more about references in the
  92.        perlref(1) man page.  Briefly, references are rather like
  93.        pointers that know what they point to.  (Objects are also
  94.        a kind of reference, but we won't be needing them right
  95.        away--if ever.)  That means that when you have something
  96.        that looks to you like an access to two-or-more-
  97.        dimensional array and/or hash, that what's really going on
  98.        is that in all these cases, the base type is merely a one-
  99.        dimensional entity that contains references to the next
  100.        level.  It's just that you can use it as though it were a
  101.        two-dimensional one.  This is actually the way almost all
  102.        C multidimensional arrays work as well.
  103.  
  104.            $list[7][12]                        # array of arrays
  105.            $list[7]{string}                    # array of hashes
  106.            $hash{string}[7]                    # hash of arrays
  107.            $hash{string}{'another string'}     # hash of hashes
  108.  
  109.        Now, because the top level only contains references, if
  110.        you try to print out your array in with a simple print()
  111.        function, you'll get something that doesn't look very
  112.        nice, like this:
  113.  
  114.            @LoL = ( [2, 3], [4, 5, 7], [0] );
  115.            print $LoL[1][2];
  116.          7
  117.            print @LoL;
  118.          ARRAY(0x83c38)ARRAY(0x8b194)ARRAY(0x8b1d0)
  119.  
  120.        That's because Perl doesn't (ever) implicitly dereference
  121.        your variables.  If you want to get at the thing a
  122.        reference is referring to, then you have to do this
  123.        yourself using either prefix typing indicators, like
  124.        ${$blah}, @{$blah}, @{$blah[$i]}, or else postfix pointer
  125.        arrows, like $a->[3], $h->{fred}, or even
  126.        $ob->method()->[3].
  127.  
  128. COMMON MISTAKES
  129.        The two most common mistakes made in constructing
  130.        something like an array of arrays is either accidentally
  131.        counting the number of elements or else taking a reference
  132.        to the same memory location repeatedly.  Here's the case
  133.        where you just get the count instead of a nested array:
  134.  
  135.            for $i (1..10) {
  136.                @list = somefunc($i);
  137.                $LoL[$i] = @list;       # WRONG!
  138.            }
  139.  
  140.        That's just the simple case of assigning a list to a
  141.        scalar and getting its element count.  If that's what you
  142.        really and truly want, then you might do well to consider
  143.        being a tad more explicit about it, like this:
  144.  
  145.            for $i (1..10) {
  146.                @list = somefunc($i);
  147.                $counts[$i] = scalar @list;
  148.            }
  149.  
  150.        Here's the case of taking a reference to the same memory
  151.        location again and again:
  152.  
  153.            for $i (1..10) {
  154.                @list = somefunc($i);
  155.                $LoL[$i] = \@list;      # WRONG!
  156.            }
  157.  
  158.        So, just what's the big problem with that?  It looks
  159.        right, doesn't it?  After all, I just told you that you
  160.        need an array of references, so by golly, you've made me
  161.        one!
  162.  
  163.        Unfortunately, while this is true, it's still broken.  All
  164.        the references in @LoL refer to the very same place, and
  165.        they will therefore all hold whatever was last in @list!
  166.        It's similar to the problem demonstrated in the following
  167.        C program:
  168.  
  169.            #include <pwd.h>
  170.            main() {
  171.                struct passwd *getpwnam(), *rp, *dp;
  172.                rp = getpwnam("root");
  173.                dp = getpwnam("daemon");
  174.  
  175.                printf("daemon name is %s\nroot name is %s\n",
  176.                        dp->pw_name, rp->pw_name);
  177.            }
  178.  
  179.        Which will print
  180.  
  181.            daemon name is daemon
  182.            root name is daemon
  183.  
  184.        The problem is that both rp and dp are pointers to the
  185.        same location in memory!  In C, you'd have to remember to
  186.        malloc() yourself some new memory.  In Perl, you'll want
  187.        to use the array constructor [] or the hash constructor {}
  188.        instead.   Here's the right way to do the preceding broken
  189.        code fragments
  190.  
  191.            for $i (1..10) {
  192.                @list = somefunc($i);
  193.                $LoL[$i] = [ @list ];
  194.            }
  195.  
  196.        The square brackets make a reference to a new array with a
  197.        copy of what's in @list at the time of the assignment.
  198.        This is what you want.
  199.  
  200.        Note that this will produce something similar, but it's
  201.        much harder to read:
  202.  
  203.            for $i (1..10) {
  204.                @list = 0 .. $i;
  205.                @{$LoL[$i]} = @list;
  206.            }
  207.  
  208.        Is it the same?  Well, maybe so--and maybe not.  The
  209.        subtle difference is that when you assign something in
  210.        square brackets, you know for sure it's always a brand new
  211.        reference with a new copy of the data.  Something else
  212.        could be going on in this new case with the @{$LoL[$i]}}
  213.        dereference on the left-hand-side of the assignment.  It
  214.        all depends on whether $LoL[$i] had been undefined to
  215.        start with, or whether it already contained a reference.
  216.        If you had already populated @LoL with references, as in
  217.            $LoL[3] = \@another_list;
  218.  
  219.        Then the assignment with the indirection on the left-hand-
  220.        side would use the existing reference that was already
  221.        there:
  222.  
  223.            @{$LoL[3]} = @list;
  224.  
  225.        Of course, this would have the "interesting" effect of
  226.        clobbering @another_list.  (Have you ever noticed how when
  227.        a programmer says something is "interesting", that rather
  228.        than meaning "intriguing", they're disturbingly more apt
  229.        to mean that it's "annoying", "difficult", or both?  :-)
  230.  
  231.        So just remember to always use the array or hash
  232.        constructors with [] or {}, and you'll be fine, although
  233.        it's not always optimally efficient.
  234.  
  235.        Surprisingly, the following dangerous-looking construct
  236.        will actually work out fine:
  237.  
  238.            for $i (1..10) {
  239.                my @list = somefunc($i);
  240.                $LoL[$i] = \@list;
  241.            }
  242.  
  243.        That's because my() is more of a run-time statement than
  244.        it is a compile-time declaration per se.  This means that
  245.        the my() variable is remade afresh each time through the
  246.        loop.  So even though it looks as though you stored the
  247.        same variable reference each time, you actually did not!
  248.        This is a subtle distinction that can produce more
  249.        efficient code at the risk of misleading all but the most
  250.        experienced of programmers.  So I usually advise against
  251.        teaching it to beginners.  In fact, except for passing
  252.        arguments to functions, I seldom like to see the gimme-a-
  253.        reference operator (backslash) used much at all in code.
  254.        Instead, I advise beginners that they (and most of the
  255.        rest of us) should try to use the much more easily
  256.        understood constructors [] and {} instead of relying upon
  257.        lexical (or dynamic) scoping and hidden reference-counting
  258.        to do the right thing behind the scenes.
  259.  
  260.        In summary:
  261.  
  262.            $LoL[$i] = [ @list ];       # usually best
  263.            $LoL[$i] = \@list;          # perilous; just how my() was that list?
  264.            @{ $LoL[$i] } = @list;      # way too tricky for most programmers
  265.  
  266. CAVEAT ON PRECEDENCE
  267.        Speaking of things like @{$LoL[$i]}, the following are
  268.        actually the same thing:
  269.  
  270.            $listref->[2][2]    # clear
  271.            $$listref[2][2]     # confusing
  272.  
  273.        That's because Perl's precedence rules on its five prefix
  274.        dereferencers (which look like someone swearing: $ @ * %
  275.        &) make them bind more tightly than the postfix
  276.        subscripting brackets or braces!  This will no doubt come
  277.        as a great shock to the C or C++ programmer, who is quite
  278.        accustomed to using *a[i] to mean what's pointed to by the
  279.        i'th element of a.  That is, they first take the
  280.        subscript, and only then dereference the thing at that
  281.        subscript.  That's fine in C, but this isn't C.
  282.  
  283.        The seemingly equivalent construct in Perl, $$listref[$i]
  284.        first does the deref of $listref, making it take $listref
  285.        as a reference to an array, and then dereference that, and
  286.        finally tell you the i'th value of the array pointed to by
  287.        $LoL. If you wanted the C notion, you'd have to write
  288.        ${$LoL[$i]} to force the $LoL[$i] to get evaluated first
  289.        before the leading $ dereferencer.
  290.  
  291. WHY YOU SHOULD ALWAYS use strict
  292.        If this is starting to sound scarier than it's worth,
  293.        relax.  Perl has some features to help you avoid its most
  294.        common pitfalls.  The best way to avoid getting confused
  295.        is to start every program like this:
  296.  
  297.            #!/usr/bin/perl -w
  298.            use strict;
  299.  
  300.        This way, you'll be forced to declare all your variables
  301.        with my() and also disallow accidental "symbolic
  302.        dereferencing".  Therefore if you'd done this:
  303.  
  304.            my $listref = [
  305.                [ "fred", "barney", "pebbles", "bambam", "dino", ],
  306.                [ "homer", "bart", "marge", "maggie", ],
  307.                [ "george", "jane", "alroy", "judy", ],
  308.            ];
  309.  
  310.            print $listref[2][2];
  311.  
  312.        The compiler would immediately flag that as an error at
  313.        compile time, because you were accidentally accessing
  314.        @listref, an undeclared variable, and it would thereby
  315.        remind you to instead write:
  316.  
  317.            print $listref->[2][2]
  318.  
  319. DEBUGGING
  320.        The standard Perl debugger in 5.001 doesn't do a very nice
  321.        job of printing out complex data structures.  However, the
  322.        perl5db that Ilya Zakharevich <ilya@math.ohio-state.edu>
  323.        wrote, which is accessible at
  324.  
  325.            ftp://ftp.perl.com/pub/perl/ext/perl5db-kit-0.9.tar.gz
  326.  
  327.        has several new features, including command line editing
  328.        as well as the x command to dump out complex data
  329.        structures.  For example, given the assignment to $LoL
  330.        above, here's the debugger output:
  331.  
  332.            DB<1> X $LoL
  333.            $LoL = ARRAY(0x13b5a0)
  334.               0  ARRAY(0x1f0a24)
  335.                  0  'fred'
  336.                  1  'barney'
  337.                  2  'pebbles'
  338.                  3  'bambam'
  339.                  4  'dino'
  340.               1  ARRAY(0x13b558)
  341.                  0  'homer'
  342.                  1  'bart'
  343.                  2  'marge'
  344.                  3  'maggie'
  345.               2  ARRAY(0x13b540)
  346.                  0  'george'
  347.                  1  'jane'
  348.                  2  'alroy'
  349.                  3  'judy'
  350.  
  351.        There's also a lower-case x command which is nearly the
  352.        same.
  353.  
  354. CODE EXAMPLES
  355.        Presented with little comment (these will get their own
  356.        man pages someday) here are short code examples
  357.        illustrating access of various types of data structures.
  358.  
  359. LISTS OF LISTS
  360.        Declaration of a LIST OF LISTS
  361.  
  362.         @LoL = (
  363.                [ "fred", "barney" ],
  364.                [ "george", "jane", "elroy" ],
  365.                [ "homer", "marge", "bart" ],
  366.              );
  367.  
  368.        Generation of a LIST OF LISTS
  369.  
  370.         # reading from file
  371.         while ( <> ) {
  372.             push @LoL, [ split ];
  373.  
  374.         # calling a function
  375.         for $i ( 1 .. 10 ) {
  376.             $LoL[$i] = [ somefunc($i) ];
  377.  
  378.         # using temp vars
  379.         for $i ( 1 .. 10 ) {
  380.             @tmp = somefunc($i);
  381.             $LoL[$i] = [ @tmp ];
  382.  
  383.         # add to an existing row
  384.         push @{ $LoL[0] }, "wilma", "betty";
  385.  
  386.        Access and Printing of a LIST OF LISTS
  387.  
  388.         # one element
  389.         $LoL[0][0] = "Fred";
  390.  
  391.         # another element
  392.         $LoL[1][1] =~ s/(\w)/\u$1/;
  393.  
  394.         # print the whole thing with refs
  395.         for $aref ( @LoL ) {
  396.             print "\t [ @$aref ],\n";
  397.  
  398.         # print the whole thing with indices
  399.         for $i ( 0 .. $#LoL ) {
  400.             print "\t [ @{$LoL[$i]} ],\n";
  401.  
  402.         # print the whole thing one at a time
  403.         for $i ( 0 .. $#LoL ) {
  404.             for $j ( 0 .. $#{$LoL[$i]} ) {
  405.                 print "elt $i $j is $LoL[$i][$j]\n";
  406.             }
  407.  
  408. HASHES OF LISTS
  409.        Declaration of a HASH OF LISTS
  410.  
  411.         %HoL = (
  412.                "flintstones"        => [ "fred", "barney" ],
  413.                "jetsons"            => [ "george", "jane", "elroy" ],
  414.                "simpsons"           => [ "homer", "marge", "bart" ],
  415.              );
  416.  
  417.        Generation of a HASH OF LISTS
  418.  
  419.         # reading from file
  420.         # flintstones: fred barney wilma dino
  421.         while ( <> ) {
  422.             next unless s/^(.*?):\s*//;
  423.             $HoL{$1} = [ split ];
  424.  
  425.         # reading from file; more temps
  426.         # flintstones: fred barney wilma dino
  427.         while ( $line = <> ) {
  428.             ($who, $rest) = split /:\s*/, $line, 2;
  429.             @fields = split ' ', $rest;
  430.             $HoL{$who} = [ @fields ];
  431.  
  432.         # calling a function that returns a list
  433.         for $group ( "simpsons", "jetsons", "flintstones" ) {
  434.             $HoL{$group} = [ get_family($group) ];
  435.  
  436.         # likewise, but using temps
  437.         for $group ( "simpsons", "jetsons", "flintstones" ) {
  438.             @members = get_family($group);
  439.             $HoL{$group} = [ @members ];
  440.  
  441.         # append new members to an existing family
  442.         push @{ $HoL{"flintstones"} }, "wilma", "betty";
  443.  
  444.        Access and Printing of a HASH OF LISTS
  445.  
  446.         # one element
  447.         $HoL{flintstones}[0] = "Fred";
  448.  
  449.         # another element
  450.         $HoL{simpsons}[1] =~ s/(\w)/\u$1/;
  451.  
  452.         # print the whole thing
  453.         foreach $family ( keys %HoL ) {
  454.             print "$family: @{ $HoL{$family} }\n"
  455.  
  456.         # print the whole thing with indices
  457.         foreach $family ( keys %HoL ) {
  458.             print "family: ";
  459.             foreach $i ( 0 .. $#{ $HoL{$family} ) {
  460.                 print " $i = $HoL{$family}[$i]";
  461.             }
  462.             print "\n";
  463.  
  464.         # print the whole thing sorted by number of members
  465.         foreach $family ( sort { @{$HoL{$b}} <=> @{$HoL{$b}} } keys %HoL ) {
  466.             print "$family: @{ $HoL{$family} }\n"
  467.  
  468.         # print the whole thing sorted by number of members and name
  469.         foreach $family ( sort { @{$HoL{$b}} <=> @{$HoL{$a}} } keys %HoL ) {
  470.             print "$family: ", join(", ", sort @{ $HoL{$family}), "\n";
  471. LISTS OF HASHES
  472.        Declaration of a LIST OF HASHES
  473.  
  474.         @LoH = (
  475.                {
  476.                   Lead      => "fred",
  477.                   Friend    => "barney",
  478.                },
  479.                {
  480.                    Lead     => "george",
  481.                    Wife     => "jane",
  482.                    Son      => "elroy",
  483.                },
  484.                {
  485.                    Lead     => "homer",
  486.                    Wife     => "marge",
  487.                    Son      => "bart",
  488.                }
  489.          );
  490.  
  491.        Generation of a LIST OF HASHES
  492.  
  493.         # reading from file
  494.         # format: LEAD=fred FRIEND=barney
  495.         while ( <> ) {
  496.             $rec = {};
  497.             for $field ( split ) {
  498.                 ($key, $value) = split /=/, $field;
  499.                 $rec->{$key} = $value;
  500.             }
  501.             push @LoH, $rec;
  502.  
  503.         # reading from file
  504.         # format: LEAD=fred FRIEND=barney
  505.         # no temp
  506.         while ( <> ) {
  507.             push @LoH, { split /[\s+=]/ };
  508.  
  509.         # calling a function  that returns a key,value list, like
  510.         # "lead","fred","daughter","pebbles"
  511.         while ( %fields = getnextpairset() )
  512.             push @LoH, { %fields };
  513.  
  514.         # likewise, but using no temp vars
  515.         while (<>) {
  516.             push @LoH, { parsepairs($_) };
  517.  
  518.         # add key/value to an element
  519.         $LoH[0]{"pet"} = "dino";
  520.         $LoH[2]{"pet"} = "santa's little helper";
  521.  
  522.        Access and Printing of a LIST OF HASHES
  523.  
  524.         # one element
  525.         $LoH[0]{"lead"} = "fred";
  526.  
  527.         # another element
  528.         $LoH[1]{"lead"} =~ s/(\w)/\u$1/;
  529.  
  530.         # print the whole thing with refs
  531.         for $href ( @LoH ) {
  532.             print "{ ";
  533.             for $role ( keys %$href ) {
  534.                 print "$role=$href->{$role} ";
  535.             }
  536.             print "}\n";
  537.  
  538.         # print the whole thing with indices
  539.         for $i ( 0 .. $#LoH ) {
  540.             print "$i is { ";
  541.             for $role ( keys %{ $LoH[$i] } ) {
  542.                 print "$role=$LoH[$i]{$role} ";
  543.             }
  544.             print "}\n";
  545.  
  546.         # print the whole thing one at a time
  547.         for $i ( 0 .. $#LoH ) {
  548.             for $role ( keys %{ $LoH[$i] } ) {
  549.                 print "elt $i $role is $LoH[$i]{$role}\n";
  550.             }
  551.  
  552. HASHES OF HASHES
  553.        Declaration of a HASH OF HASHES
  554.  
  555.         %HoH = (
  556.                "flintstones" => {
  557.                    "lead"    => "fred",
  558.                    "pal"     => "barney",
  559.                },
  560.                "jetsons"     => {
  561.                     "lead"   => "george",
  562.                     "wife"   => "jane",
  563.                     "his boy"=> "elroy",
  564.                 }
  565.                "simpsons"    => {
  566.                     "lead"   => "homer",
  567.                     "wife"   => "marge",
  568.                     "kid"    => "bart",
  569.              );
  570.  
  571.        Generation of a HASH OF HASHES
  572.  
  573.         # reading from file
  574.         # flintstones: lead=fred pal=barney wife=wilma pet=dino
  575.         while ( <> ) {
  576.             next unless s/^(.*?):\s*//;
  577.             $who = $1;
  578.             for $field ( split ) {
  579.                 ($key, $value) = split /=/, $field;
  580.                 $HoH{$who}{$key} = $value;
  581.             }
  582.  
  583.         # reading from file; more temps
  584.         while ( <> ) {
  585.             next unless s/^(.*?):\s*//;
  586.             $who = $1;
  587.             $rec = {};
  588.             $HoH{$who} = $rec;
  589.             for $field ( split ) {
  590.                 ($key, $value) = split /=/, $field;
  591.                 $rec->{$key} = $value;
  592.             }
  593.  
  594.         # calling a function  that returns a key,value list, like
  595.         # "lead","fred","daughter","pebbles"
  596.         while ( %fields = getnextpairset() )
  597.             push @a, { %fields };
  598.  
  599.         # calling a function  that returns a key,value hash
  600.         for $group ( "simpsons", "jetsons", "flintstones" ) {
  601.             $HoH{$group} = { get_family($group) };
  602.  
  603.         # likewise, but using temps
  604.         for $group ( "simpsons", "jetsons", "flintstones" ) {
  605.             %members = get_family($group);
  606.             $HoH{$group} = { %members };
  607.  
  608.         # append new members to an existing family
  609.         %new_folks = (
  610.             "wife" => "wilma",
  611.             "pet"  => "dino";
  612.         );
  613.         for $what (keys %new_folks) {
  614.             $HoH{flintstones}{$what} = $new_folks{$what};
  615.  
  616.        Access and Printing of a HASH OF HASHES
  617.  
  618.         # one element
  619.         $HoH{"flintstones"}{"wife"} = "wilma";
  620.  
  621.         # another element
  622.         $HoH{simpsons}{lead} =~ s/(\w)/\u$1/;
  623.  
  624.         # print the whole thing
  625.         foreach $family ( keys %HoH ) {
  626.             print "$family: ";
  627.             for $role ( keys %{ $HoH{$family} } {
  628.                 print "$role=$HoH{$family}{$role} ";
  629.             }
  630.             print "}\n";
  631.  
  632.         # print the whole thing  somewhat sorted
  633.         foreach $family ( sort keys %HoH ) {
  634.             print "$family: ";
  635.             for $role ( sort keys %{ $HoH{$family} } {
  636.                 print "$role=$HoH{$family}{$role} ";
  637.             }
  638.             print "}\n";
  639.  
  640.         # print the whole thing sorted by number of members
  641.         foreach $family ( sort { keys %{$HoH{$b}} <=> keys %{$HoH{$b}} } keys %HoH ) {
  642.             print "$family: ";
  643.             for $role ( sort keys %{ $HoH{$family} } {
  644.                 print "$role=$HoH{$family}{$role} ";
  645.             }
  646.             print "}\n";
  647.  
  648.         # establish a sort order (rank) for each role
  649.         $i = 0;
  650.         for ( qw(lead wife son daughter pal pet) ) { $rank{$_} = ++$i }
  651.  
  652.         # now print the whole thing sorted by number of members
  653.         foreach $family ( sort { keys %{$HoH{$b}} <=> keys %{$HoH{$b}} } keys %HoH ) {
  654.             print "$family: ";
  655.             # and print these according to rank order
  656.             for $role ( sort { $rank{$a} <=> $rank{$b} keys %{ $HoH{$family} } {
  657.                 print "$role=$HoH{$family}{$role} ";
  658.             }
  659.             print "}\n";
  660.  
  661. MORE ELABORATE RECORDS
  662.        Declaration of MORE ELABORATE RECORDS
  663.  
  664.        Here's a sample showing how to create and use a record
  665.        whose fields are of many different sorts:
  666.  
  667.             $rec = {
  668.                 STRING  => $string,
  669.                 LIST    => [ @old_values ],
  670.                 LOOKUP  => { %some_table },
  671.                 FUNC    => \&some_function,
  672.                 FANON   => sub { $_[0] ** $_[1] },
  673.                 FH      => \*STDOUT,
  674.             };
  675.  
  676.             print $rec->{STRING};
  677.  
  678.             print $rec->{LIST}[0];
  679.             $last = pop @ { $rec->{LIST} };
  680.  
  681.             print $rec->{LOOKUP}{"key"};
  682.             ($first_k, $first_v) = each %{ $rec->{LOOKUP} };
  683.  
  684.             $answer = &{ $rec->{FUNC} }($arg);
  685.             $answer = &{ $rec->{FANON} }($arg1, $arg2);
  686.  
  687.             # careful of extra block braces on fh ref
  688.             print { $rec->{FH} } "a string\n";
  689.  
  690.             use FileHandle;
  691.             $rec->{FH}->autoflush(1);
  692.             $rec->{FH}->print(" a string\n");
  693.  
  694.        Declaration of a HASH OF COMPLEX RECORDS
  695.  
  696.             %TV = (
  697.                "flintstones" => {
  698.                    series   => "flintstones",
  699.                    nights   => [ qw(monday thursday friday) ];
  700.                    members  => [
  701.                        { name => "fred",    role => "lead", age  => 36, },
  702.                        { name => "wilma",   role => "wife", age  => 31, },
  703.                        { name => "pebbles", role => "kid", age  =>  4, },
  704.                    ],
  705.                },
  706.  
  707.                "jetsons"     => {
  708.                    series   => "jetsons",
  709.                    nights   => [ qw(wednesday saturday) ];
  710.                    members  => [
  711.                        { name => "george",  role => "lead", age  => 41, },
  712.                        { name => "jane",    role => "wife", age  => 39, },
  713.                        { name => "elroy",   role => "kid",  age  =>  9, },
  714.                    ],
  715.                 },
  716.  
  717.                "simpsons"    => {
  718.                    series   => "simpsons",
  719.                    nights   => [ qw(monday) ];
  720.                    members  => [
  721.                        { name => "homer", role => "lead", age  => 34, },
  722.                        { name => "marge", role => "wife", age => 37, },
  723.                        { name => "bart",  role => "kid",  age  =>  11, },
  724.                    ],
  725.                 },
  726.              );
  727.  
  728.        Generation of a HASH OF COMPLEX RECORDS
  729.  
  730.             # reading from file
  731.             # this is most easily done by having the file itself be
  732.             # in the raw data format as shown above.  perl is happy
  733.             # to parse complex datastructures if declared as data, so
  734.             # sometimes it's easiest to do that
  735.  
  736.             # here's a piece by piece build up
  737.             $rec = {};
  738.             $rec->{series} = "flintstones";
  739.             $rec->{nights} = [ find_days() ];
  740.  
  741.             @members = ();
  742.             # assume this file in field=value syntax
  743.             while () {
  744.                 %fields = split /[\s=]+/;
  745.                 push @members, { %fields };
  746.             }
  747.             $rec->{members} = [ @members ];
  748.  
  749.             # now remember the whole thing
  750.             $TV{ $rec->{series} } = $rec;
  751.  
  752.             ###########################################################
  753.             # now, you might want to make interesting extra fields that
  754.             # include pointers back into the same data structure so if
  755.             # change one piece, it changes everywhere, like for examples
  756.             # if you wanted a {kids} field that was an array reference
  757.             # to a list of the kids' records without having duplicate
  758.             # records and thus update problems.
  759.             ###########################################################
  760.             foreach $family (keys %TV) {
  761.                 $rec = $TV{$family}; # temp pointer
  762.                 @kids = ();
  763.                 for $person ( @{$rec->{members}} ) {
  764.                     if ($person->{role} =~ /kid|son|daughter/) {
  765.                         push @kids, $person;
  766.                     }
  767.                 }
  768.                 # REMEMBER: $rec and $TV{$family} point to same data!!
  769.                 $rec->{kids} = [ @kids ];
  770.             }
  771.  
  772.             # you copied the list, but the list itself contains pointers
  773.             # to uncopied objects. this means that if you make bart get
  774.             # older via
  775.  
  776.             $TV{simpsons}{kids}[0]{age}++;
  777.  
  778.             # then this would also change in
  779.             print $TV{simpsons}{members}[2]{age};
  780.  
  781.             # because $TV{simpsons}{kids}[0] and $TV{simpsons}{members}[2]
  782.             # both point to the same underlying anonymous hash table
  783.  
  784.             # print the whole thing
  785.             foreach $family ( keys %TV ) {
  786.                 print "the $family";
  787.                 print " is on during @{ $TV{$family}{nights} }\n";
  788.                 print "its members are:\n";
  789.                 for $who ( @{ $TV{$family}{members} } ) {
  790.                     print " $who->{name} ($who->{role}), age $who->{age}\n";
  791.                 }
  792.                 print "it turns out that $TV{$family}{'lead'} has ";
  793.                 print scalar ( @{ $TV{$family}{kids} } ), " kids named ";
  794.                 print join (", ", map { $_->{name} } @{ $TV{$family}{kids} } );
  795.                 print "\n";
  796.             }
  797.  
  798. Database Ties
  799.        You cannot easily tie a multilevel data structure (such as
  800.        a hash of hashes) to a dbm file.  The first problem is
  801.        that all but GDBM and Berkeley DB have size limitations,
  802.        but beyond that, you also have problems with how
  803.        references are to be represented on disk.  One
  804.        experimental module that does attempt to partially address
  805.        this need is the MLDBM module.  Check your nearest CPAN
  806.        site as described in the perlmod manpage for source code
  807.        to MLDBM.
  808.  
  809. SEE ALSO
  810.        the perlref manpage, the perllol manpage, the perldata
  811.        manpage, the perlobj manpage
  812.  
  813. AUTHOR
  814.        Tom Christiansen <tchrist@perl.com>
  815.  
  816.        Last update: Tue Dec 12 09:20:26 MST 1995
  817.